<template>
  <div id="gaosu-x6"></div>
</template>

<script>
import { register } from '@antv/x6-vue-shape'
import gsNode from '@/views/x6node/gsNode.vue'
import { Graph, Timing } from '@antv/x6'
import { px2px } from '@/utils/flexible'

const groupAttrs = {
  body: {
    fill: '#cee7fb',
    stroke: '#75B9FC',
    strokeWidth: 1,
    rx: px2px(10),
    ry: px2px(10),
  },
}

export default {
  name: 'gaosu',
  data() {
    return {
      graph: null,
      group1: {
        node: null,
        padding: 24,
        gap: 20,
        child1: null,
        child2: null,
        child3: null,
        child4: null,
        child5: null,
      },
      group2: {
        node: null,
        padding: 24,
        gap: 20,
        child1: null,
      },
      group3: {
        node: null,
        padding: 24,
        gap: 12,
        child1: null,
        child2: null,
      },
    }
  },
  computed: {
    getLayout() {
      return (node) => {
        if (!node) return {}

        return {
          ...node.position(),
          ...node.size(),
        }
      }
    },
  },
  mounted() {
    this.registerNodes()

    this.initGraph()

    this.initGroups()
    this.initChildren()
    this.addNodeInGroup()
    this.initEdges()

    this.setNodeData()

    this.startAnimation()

    this.graph.centerContent()
  },
  methods: {
    // 注册节点
    registerNodes() {
      register({
        shape: 'gsNode',
        width: 100,
        height: 100,
        component: gsNode,
      })
    },
    // 初始化图形
    initGraph() {
      this.graph = new Graph({
        container: document.getElementById('gaosu-x6'),
        width: '100%',
        height: px2px(754),
        background: {
          color: '#F2F7FA',
        },
      })
    },
    // 创建组
    initGroups() {
      this.group1.node = this.graph.addNode({
        id: 'group1',
        x: px2px(32),
        y: px2px(1),
        width: px2px(1472),
        height: px2px(304),
        zIndex: 1,
        attrs: groupAttrs,
      })

      const {
        x: group1x,
        y: group1y,
        width: group1weight,
        height: group1height,
      } = this.getLayout(this.group1.node)
      this.group2.node = this.graph.addNode({
        id: 'group2',
        x: group1x,
        y: group1y + group1height + px2px(16),
        width: group1weight,
        height: px2px(208),
        zIndex: 1,
        attrs: groupAttrs,
      })

      const { y: group2y, height: group2height } = this.getLayout(
        this.group2.node
      )
      this.group3.node = this.graph.addNode({
        id: 'group3',
        x: group1x,
        y: group2y + group2height + px2px(16),
        width: group1weight,
        height: px2px(208),
        zIndex: 1,
        attrs: groupAttrs,
      })
    },
    // 创建子节点
    initChildren() {
      const group1Layout = this.getLayout(this.group1.node)
      this.group1.child1 = this.graph.addNode({
        id: 'child11',
        shape: 'gsNode',
        x: group1Layout.x + px2px(24),
        y: group1Layout.y + px2px(24),
        width: px2px(704),
        height: px2px(256),
        zIndex: 10,
      })
      const child11Layout = this.getLayout(this.group1.child1)
      this.group1.child2 = this.graph.addNode({
        id: 'child12',
        shape: 'gsNode',
        x: child11Layout.x + child11Layout.width + px2px(this.group1.gap),
        y: group1Layout.y + px2px(this.group1.padding),
        width: px2px(160),
        height: px2px(256),
        zIndex: 10,
      })
      const child12Layout = this.getLayout(this.group1.child2)
      this.group1.child3 = this.graph.addNode({
        id: 'child13',
        shape: 'gsNode',
        x: child12Layout.x + child12Layout.width + px2px(this.group1.gap),
        y: group1Layout.y + px2px(this.group1.padding),
        width: px2px(160),
        height: px2px(256),
        zIndex: 10,
      })
      const child13Layout = this.getLayout(this.group1.child3)
      this.group1.child4 = this.graph.addNode({
        id: 'child14',
        shape: 'gsNode',
        x: child13Layout.x + child13Layout.width + px2px(this.group1.gap),
        y: group1Layout.y + px2px(this.group1.padding),
        width: px2px(160),
        height: px2px(256),
        zIndex: 10,
      })
      const child14Layout = this.getLayout(this.group1.child4)
      this.group1.child5 = this.graph.addNode({
        id: 'child15',
        shape: 'gsNode',
        x: child14Layout.x + child14Layout.width + px2px(this.group1.gap),
        y: group1Layout.y + px2px(this.group1.padding),
        width: px2px(160),
        height: px2px(256),
        zIndex: 10,
      })

      const group2Layout = this.getLayout(this.group2.node)
      this.group2.child1 = this.graph.addNode({
        id: 'child21',
        shape: 'gsNode',
        x: (group2Layout.x + group2Layout.width - px2px(816)) / 2,
        y: group2Layout.y + this.group2.padding,
        width: px2px(816),
        height: px2px(160),
        zIndex: 10,
      })

      const group3Layout = this.getLayout(this.group3.node)
      this.group3.child1 = this.graph.addNode({
        id: 'child31',
        shape: 'gsNode',
        x: group3Layout.x + this.group3.padding,
        y: group3Layout.y + this.group2.padding,
        width: px2px(768),
        height: px2px(160),
        zIndex: 10,
      })
      const child31Layout = this.getLayout(this.group3.child1)
      this.group3.child2 = this.graph.addNode({
        id: 'child32',
        shape: 'gsNode',
        x: child31Layout.x + child31Layout.width + this.group3.gap,
        y: group3Layout.y + this.group2.padding,
        width: px2px(644),
        height: px2px(160),
        zIndex: 10,
      })
    },
    // 将子节点加入组
    addNodeInGroup() {
      this.group1.node.addChild(this.group1.child1)
      this.group1.node.addChild(this.group1.child2)
      this.group1.node.addChild(this.group1.child3)
      this.group1.node.addChild(this.group1.child4)
      this.group1.node.addChild(this.group1.child5)

      this.group2.node.addChild(this.group2.child1)

      this.group3.node.addChild(this.group3.child1)
      this.group3.node.addChild(this.group3.child2)
    },
    // 创建边
    initEdges() {
      const child11Layout = this.getLayout(this.group1.child1)
      const child15Layout = this.getLayout(this.group1.child5)
      const child21Layout = this.getLayout(this.group2.child1)
      const child31Layout = this.getLayout(this.group3.child1)
      const child32Layout = this.getLayout(this.group3.child2)
      this.graph.addEdges([
        {
          id: '11-21',
          shape: 'gs-edge',
          source: {
            cell: this.group1.child1,
            anchor: {
              name: 'left',
            },
          },
          target: {
            cell: this.group2.child1,
            anchor: {
              name: 'left',
            },
          },
          vertices: [
            { x: px2px(6), y: child11Layout.y + child11Layout.height / 2 },
            { x: px2px(6), y: child21Layout.y + child21Layout.height / 2 },
          ],
          connector: {
            name: 'rounded',
          },
          attrs: {
            label: {
              textPath: { selector: 'line', startOffset: '14%' },
              textAnchor: 20,
              textVerticalAnchor: 20,
              text: '业务服务集成',
              style: {
                writingMode: 'vertical-lr',
                transform: `translateX(${px2px(14)}px)`,
                letterSpacing: `${px2px(6)}px`,
              },
            },
          },
        },
      ])
      this.graph.addEdges([
        {
          id: '15-32',
          shape: 'gs-edge',
          source: {
            cell: this.group1.child5,
            anchor: {
              name: 'right',
            },
          },
          target: {
            cell: this.group3.child2,
            anchor: {
              name: 'right',
            },
          },
          vertices: [
            { x: px2px(1524), y: child15Layout.y + child15Layout.height / 2 },
            { x: px2px(1524), y: child32Layout.y + child32Layout.height / 2 },
          ],
          connector: {
            name: 'rounded',
          },
          attrs: {
            label: {
              textPath: { selector: 'line', startOffset: '45%' },
              textAnchor: 'middle',
              textVerticalAnchor: 16,
              text: '数据集成',
              style: {
                writingMode: 'vertical-lr',
                transform: `translateX(${px2px(-14)}px)`,
                letterSpacing: `${px2px(6)}px`,
              },
            },
          },
        },
      ])

      this.graph.addEdges([
        {
          id: '21-31',
          shape: 'gs-edge',
          source: {
            cell: this.group3.child1,
            anchor: {
              name: 'top',
            },
          },
          target: {
            cell: this.group2.child1,
            anchor: {
              name: 'bottom',
            },
          },
          vertices: [
            { x: child31Layout.x + child31Layout.width / 2, y: px2px(536) },
            { x: child21Layout.x + child21Layout.width / 2, y: px2px(536) },
          ],
          connector: {
            name: 'rounded',
          },
          attrs: {
            label: {
              textPath: { selector: 'line', startOffset: '50%' },
              textAnchor: 'middle',
              textVerticalAnchor: 15,
              text: '技术服务集成',
              style: {
                backgroundColor: 'pink',
              },
            },
            label1: {
              textPath: { selector: 'line', startOffset: '50%' },
              textAnchor: 'middle',
              textVerticalAnchor: -6,
              text: '业务服务集成',
              cx: 50,
            },
          },
        },
      ])
      this.graph.addEdges([
        {
          id: '21-32',
          shape: 'gs-edge',
          source: {
            cell: this.group2.child1,
            anchor: {
              name: 'bottom',
            },
          },
          target: {
            cell: this.group3.child2,
            anchor: {
              name: 'top',
            },
          },
          vertices: [
            { x: child21Layout.x + child21Layout.width / 2, y: px2px(536) },
            { x: child32Layout.x + child32Layout.width / 2, y: px2px(536) },
          ],
          connector: {
            name: 'rounded',
          },
          attrs: {
            label: {
              textPath: { selector: 'line', startOffset: '50%' },
              textAnchor: 'middle',
              textVerticalAnchor: -6,
              text: '数据服务集成',
            },
          },
        },
      ])
    },
    // 给节点赋值
    setNodeData() {
      let length = 0

      this.graph.on('view:mounted', () => {
        length++
        if (length < this.graph.getCellCount()) {
          return
        }

        this.group1.child1.setData({
          title: 'xxxx平台（M）',
          column: 5,
          list: [
            { label: '统一门户', type: 'disabled' },
            { label: '投资管理', type: 'disabled' },
            { label: 'xxxx管理系统', type: 'disabled' },
            { label: 'xx管理系统', type: 'disabled' },
            { label: 'xx管理系统', type: 'disabled' },
            { label: '领导驾驶舱App' },
            { label: 'xxxx管理系统' },
            { label: '经营分析' },
            { label: 'xx管理系统' },
            { label: 'xxxxx管理系统' },
            { label: 'xxx管理系统', type: 'disabled' },
            { label: 'xx管理系统', type: 'disabled' },
            { label: 'xx管理系统' },
            { label: 'xx官网' },
            { label: 'xxxx管理系统', type: 'primary' },
            { label: 'xx管理系统', type: 'disabled' },
            { label: 'xx管理系统', type: 'primary' },
            { label: 'xx管理系统', type: 'primary' },
            { label: 'xx统一App', type: 'primary' },
          ],
        })
        this.group1.child2.setData({
          title: 'xx管理平台（C）',
          column: 1,
          list: [
            { label: '智慧建管', type: 'disabled' },
            { label: '指挥中心' },
            { label: '智慧设计' },
            { label: '智慧建造' },
          ],
        })
        this.group1.child3.setData({
          title: 'xx管理平台（O）',
          column: 1,
          list: [
            { label: '养护管理', type: 'disabled' },
            { label: '应急安全管理', type: 'primary' },
            { label: '路产管理' },
            { label: '收费管理' },
          ],
        })
        this.group1.child4.setData({
          title: '路网中心（R）',
          column: 1,
          list: [
            { label: '路网监控' },
            { label: '应急调度' },
            { label: 'xx管理系统', type: 'disabled' },
            { label: 'xxxxxx管理系统', type: 'disabled' },
          ],
        })
        this.group1.child5.setData({
          title: '产业经营（I）',
          column: 1,
          list: [
            { label: '服务区管理' },
            { label: '-', type: 'hidden' },
            { label: '-', type: 'hidden' },
            { label: '-', type: 'hidden' },
          ],
        })

        this.group2.child1.setData({
          title: '业务中台',
          column: 6,
          itemWidth: 124,
          list: [
            { label: '统一门户', type: 'disabled' },
            { label: '投资管理', type: 'disabled' },
            { label: 'xxxx管理系统', type: 'disabled' },
            { label: 'xx管理系统', type: 'disabled' },
            { label: 'xx管理系统', type: 'disabled' },
            { label: 'xx管理系统', type: 'disabled' },
            { label: '领导驾驶舱App' },
            { label: 'xxxx管理系统' },
            { label: '经营分析' },
            { label: 'xx管理系统' },
            { label: 'xxxxx管理系统' },
          ],
        })

        this.group3.child1.setData({
          title: '技术中台（T）',
          column: 6,
          itemWidth: 116,
          list: [
            { label: 'xxxxxx系统', type: 'primary' },
            { label: '统一认证' },
            { label: 'GIS 地图' },
            { label: '容器管理' },
            { label: '短信平台' },
            { label: 'BIM 引擎', type: 'primary' },
            { label: '主数据系统' },
            { label: '统一文档' },
            { label: '电子签章' },
            { label: '工作流引擎' },
            { label: '统一报表' },
            { label: '三维可视化' },
          ],
        })
        this.group3.child2.setData({
          title: '数据中台（D）',
          column: 5,
          itemWidth: 116,
          list: [
            { label: '人力资源治理' },
            { label: '资产数据治理' },
            { label: '主数据' },
            { label: '业务数据汇聚' },
            { label: '基础数据', type: 'disabled' },
            { label: '财务数据' },
            { label: '资产数据' },
          ],
        })
      })
    },
    createFlowAnimation(edge, reverse = false) {
      const startPosition = reverse ? 1 : 0
      const endPosition = reverse ? 0 : 1
      const duration = 4000
      const options = {
        delay: 0,
        duration: 0,
        timing: Timing.linear,
        start() {
          edge.updateAttrs(
            {
              circle: {
                r: px2px(4),
                atConnectionRatio: startPosition,
                fill: {
                  type: 'radialGradient',
                  stops: [
                    { offset: '0%', color: '#FFF' },
                    { offset: '100%', color: '#6692FF' },
                  ],
                },
              },
            },
            { silent: true }
          )
        },
        finish() {
          edge.updateAttrs(
            {
              circle: {
                atConnectionRatio: startPosition,
                stroke: 'transparent',
                fill: 'transparent',
              },
            },
            { silent: true }
          )
          options.duration = duration
          edge.transition(
            'attrs/circle/atConnectionRatio',
            endPosition,
            options
          )
        },
      }

      edge.transition('attrs/circle/atConnectionRatio', endPosition, options)
    },
    startAnimation() {
      const edge1 = this.graph.getCellById('11-21')
      const edge2 = this.graph.getCellById('15-32')
      const edge3 = this.graph.getCellById('21-31')
      const edge4 = this.graph.getCellById('21-32')

      this.createFlowAnimation(edge1)
      this.createFlowAnimation(edge2)
      this.createFlowAnimation(edge3, true)
      this.createFlowAnimation(edge4)
    },
  },
}
</script>

<style scoped></style>
